﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using Water.Web;
using Water.Web.Controls;
using System.ComponentModel;
using System.Drawing.Design;
using Water.Web.Controls.BaseInterface;
using Water.Resources.Globalize;
using System.Collections.Specialized;
using System.Data;


[assembly: WebResource("Water.Resources.Default.JS.GridView.Grid.js", "text/javascript")]
namespace Water.Web.Controls
{
    [ParseChildren(true, "Columns")]
    public partial class ListView : System.Web.UI.WebControls.ListView, ICallBackable, IUpdatedableControl, IQuery, IAutoQuery
    {
        #region private properties

        private bool isCallBack = false;
        private string displayDuringCallBackTextControls;

        private bool isUpdateAfterCallBack = false;
        private UpdatedableControlRenderMode renderMode = UpdatedableControlRenderMode.Div;
        private string duringCallBackText = "";
        private string updateJS = "";
        private bool showFooter = false;

        private StringBuilder gridSetting = new StringBuilder();

        private Unit gridHeight;
        private Unit gridWidth;
        private bool displayGridBorder = false;
        private ITemplate pagerTemplate;

        private string packageId = "";

        private const string defaultHeaderCellWidth = "150";

        private bool autoQuery = false;

        /*
         * The DataBind method of the ListView control has a re-entrancy problem which causes redundant data-binding to take place when the ListView is bound to a data source control. This 
         * 通过该标记解决ListView的重复绑定的issus
         */
        private bool boundFlag = false;

        private DataControlFieldCollection _fieldCollection;

        private static readonly object EventCellDataBound = new object();

        private bool isSelecting = false;

        private string queryTarget;

        private List<string> querySource = new List<string>();

        private DataView matrixColumns = new DataView();

        [Browsable(false)]
        public DataView MatrixColumns
        {
            get
            {
                if (null == matrixColumns.Table)
                {
                    IDataSource _ds = this.GetDataSource();
                    if (_ds is Water.Web.Controls.ObjectDataSource)
                    {
                        Water.Web.Controls.ObjectDataSource _wds = _ds as Water.Web.Controls.ObjectDataSource;
                        this.matrixColumns = _wds.MatrixColumns;
                    }
                }
                return matrixColumns;
            }
            set { matrixColumns = value; }
        }

        #endregion

        #region ICallBackable 成员

        [Browsable(true), GlobalizeCategory("AJAX"), GlobalizeDescription("IsCallBack"), DefaultValue(false)]
        public bool IsCallBack
        {
            get
            {
                return this.isCallBack;
            }
            set
            {
                this.isCallBack = value;
            }
        }
        [Browsable(true), GlobalizeCategory("AJAX"), GlobalizeDescription("CallBackTargets")]
        public string CallBackTargets
        {
            get
            {
                if (this.IsCallBack)
                {
                    return this.displayDuringCallBackTextControls;
                }
                return string.Empty;
            }
            set
            {
                this.displayDuringCallBackTextControls = value;
            }
        }

        #endregion

        #region IUpdatedableControl 成员
        [Browsable(true), GlobalizeCategory("AJAX"), GlobalizeDescription("AutoUpdatedAfterCallBack"), DefaultValue(false)]
        public bool AutoUpdatedAfterCallBack
        {
            get
            {
                return this.isUpdateAfterCallBack;
            }
            set
            {
                this.isUpdateAfterCallBack = value;
            }
        }
        [Browsable(false), DefaultValue(false)]
        public bool IsUpdatedAfterCallBack
        {
            get
            {
                return this.isUpdateAfterCallBack;
            }
            set
            {
                this.isUpdateAfterCallBack = value;
            }
        }

        [Browsable(true), GlobalizeCategory("AJAX"), GlobalizeDescription("DuringCallBackText")]
        public string DuringCallBackText
        {
            get
            {
                if (this.duringCallBackText != null)
                {
                    return this.duringCallBackText;
                }
                return string.Empty;
            }
            set
            {
                this.duringCallBackText = value;
            }
        }
        [Browsable(true), GlobalizeCategory("AJAX"), GlobalizeDescription("RenderMode"), DefaultValue(UpdatedableControlRenderMode.Span)]
        public UpdatedableControlRenderMode RenderMode
        {
            get
            {
                return this.renderMode;
            }
            set
            {
                this.renderMode = value;
            }
        }

        [Browsable(false), GlobalizeCategory("AJAX"), GlobalizeDescription("UpdateJS"), DefaultValue("")]
        public virtual string UpdateJS
        {
            get
            {
                return this.updateJS;
            }
            set
            {
                this.updateJS = value;
            }
        }

        private List<string> callBackControls = new List<string>();
        [Browsable(false)]
        public List<string> CallBackControls
        {
            get { return callBackControls; }
            set { callBackControls = value; }
        }
        #endregion

        #region Event

        public event ListViewCellDataBoundEventHandler CellDataBound
        {
            add
            {
                base.Events.AddHandler(EventCellDataBound, value);
            }
            remove
            {
                base.Events.RemoveHandler(EventCellDataBound, value);
            }
        }

        #endregion

        [Browsable(true), GlobalizeDescription("GridHeight"), Category("Appearance")]
        public Unit GridHeight
        {
            get { return gridHeight; }
            set { gridHeight = value; }
        }

        [Browsable(true), GlobalizeDescription("GridWidth"), Category("Appearance")]
        public Unit GridWidth
        {
            get { return gridWidth; }
            set { gridWidth = value; }
        }

        [Browsable(true), GlobalizeDescription("DisplayGridBorder"), Category("Appearance"), DefaultValue(false)]
        public bool DisplayGridBorder
        {
            get { return displayGridBorder; }
            set { displayGridBorder = value; }
        }

        [Browsable(true), GlobalizeDescription("ShowFooter"), Category("Appearance"), DefaultValue(false)]
        public bool ShowFooter
        {
            get { return showFooter; }
            set
            {
                showFooter = value;
                if (showFooter)
                    gridSetting.Append(",showFooter:true");
                else
                    gridSetting.Replace(",showFooter:true", "");
            }
        }

        #region IAutoQuery 成员
        [Browsable(true), GlobalizeDescription("AutoQuery"), Category("Behavior"), DefaultValue(false)]
        public bool AutoQuery
        {
            get { return autoQuery; }
            set { autoQuery = value; }
        }
        #endregion

        public virtual void OnCellDataBound(ListViewCellDataBoundEventArgs e)
        {
            ListViewCellDataBoundEventHandler handler = (ListViewCellDataBoundEventHandler)base.Events[EventCellDataBound];
            if (handler != null)
            {
                handler(this, e);
            }
        }


        [GlobalizeDescription("Columns"), GlobalizeCategory("Data"), Editor("System.Web.UI.Design.WebControls.DataControlFieldTypeEditor, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", typeof(UITypeEditor)), PersistenceMode(PersistenceMode.InnerProperty), DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        public virtual DataControlFieldCollection Columns
        {
            get
            {
                if (this._fieldCollection == null)
                {
                    this._fieldCollection = new DataControlFieldCollection();
                    this._fieldCollection.FieldsChanged += new EventHandler(this.OnFieldsChanged);
                    if (base.IsTrackingViewState)
                    {
                        ((IStateManager)this._fieldCollection).TrackViewState();
                    }
                }
                return this._fieldCollection;
            }
        }

        [Browsable(false)]
        [TemplateContainer(typeof(ListView))]
        [PersistenceMode(PersistenceMode.InnerProperty)]
        public ITemplate PagerTemplate
        {
            get { return pagerTemplate; }
            set
            {
                pagerTemplate = value;
                if (null != pagerTemplate)
                    gridSetting.Append(",pagerAble:true");
                else
                    gridSetting.Replace(",pagerAble:true", "");
            }
        }

        private void OnFieldsChanged(object sender, EventArgs e)
        {
            if (base.Initialized)
            {
                base.RequiresDataBinding = true;
            }
        }

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
            PageManager.Register(this);
            this.Page.ClientScript.RegisterClientScriptResource(typeof(GridView), "Water.Resources.Default.JS.GridView.Grid.js");
            PageManager.RegisterPageStyleSheet(this, "Grid_CSS", "CSS/Grid.css");
            if (this.Columns.Count > 0)
                this.packageId = this.ClientID + "_p";

            DataSourceView data = this.GetData();
        }

        /*
        void ListView_LayoutCreated(object sender, EventArgs e)
        {
            //matrix
            IDataSource _ds = this.GetDataSource();
            if (_ds is Water.Web.Controls.ObjectDataSource)
            {
                Water.Web.Controls.ObjectDataSource _wds = _ds as Water.Web.Controls.ObjectDataSource;
                this.matrixColumns = _wds.MatrixColumns;
            }

            //matrix
        }
        */

        protected override void Render(HtmlTextWriter writer)
        {
            RenderBeginTag(writer);
            base.Render(writer);
            RenderEndTag(writer);
            if (this.Columns.Count > 0)
            {
                string js;
                if (gridSetting.Length > 0)
                {
                    string _setting = "{" + gridSetting.ToString().Substring(1) + "}";
                    js = @"$j('#" + this.packageId + "').grid(" + _setting + ");";
                }
                else
                    js = @"$j('#" + this.packageId + "').grid();";
                js = @"$j(function() {" + js + "});";
                this.Page.ClientScript.RegisterStartupScript(typeof(ListView), this.UniqueID, js + "\n", true);
            }
        }

        public override void RenderBeginTag(HtmlTextWriter writer)
        {
            //if (this is IUpdatedableControl)
            //{
            //    if (this.Columns.Count > 0)
            //        Marker.WriteAJAXBegin(writer, this, false, RenderPackager);
            //    else
            //        Marker.WriteAJAXBegin(writer, this);
            //}
            //base.RenderBeginTag(writer);
            if (this.Columns.Count > 0)
            {
                RenderPackager(writer);
                writer.AddAttribute(HtmlTextWriterAttribute.Id, this.packageId);
                writer.RenderBeginTag(HtmlTextWriterTag.Div);
            }
        }

        public override void RenderEndTag(HtmlTextWriter writer)
        {
            //base.RenderEndTag(writer);
            //if (this is IUpdatedableControl)
            //    Marker.WriteAJAXEnd(writer, this);
            if (this.Columns.Count > 0)
            {
                writer.RenderEndTag();
            }
        }

        protected override void CreateChildControls()
        {
            this.Controls.Clear();

            if (this.Columns.Count > 0)
            {
                if (null == this.ItemTemplate)
                    this.ItemTemplate = new DefaultItemTemplate(this);
                if (DesignMode)
                    this.ItemTemplate.InstantiateIn(this);
                if (null == AlternatingItemTemplate)
                    this.AlternatingItemTemplate = new DefaultAlternatingItemTemplate(this);
                if (null == this.LayoutTemplate)
                    this.LayoutTemplate = new DefaultLayoutTemplate(this);
                if (DesignMode)
                    this.LayoutTemplate.InstantiateIn(this);
                if (null == this.EmptyDataTemplate)
                    this.EmptyDataTemplate = new DefaultEmptyDataTemplate(this);
            }

            base.CreateChildControls();
        }

        /*
        protected override int CreateChildControls(IEnumerable dataSource, bool dataBinding)
        {
            //matrix
            IDataSource _ds = this.GetDataSource();
            if (_ds is Water.Web.Controls.ObjectDataSource)
            {
                Water.Web.Controls.ObjectDataSource _wds = _ds as Water.Web.Controls.ObjectDataSource;
                this.matrixColumns = _wds.MatrixColumns;
            }
            EnsureLayoutTemplate();
            //matrix
            return base.CreateChildControls(dataSource, dataBinding);
        }
        */

        protected override void PerformDataBinding(IEnumerable data)
        {
            //通过该标记解决ListView的重复绑定的issus
            if (!boundFlag)
            {
                base.PerformDataBinding(data);
                this.boundFlag = true;
            }
        }
        /*
        protected override void EnsureLayoutTemplate()
        {
            //base.EnsureLayoutTemplate();
        }
        protected virtual void EnsureLayoutTemplateEx()
        {
            base.EnsureLayoutTemplate();

        }
         */


        protected override void PerformSelect()
        {
            this.EnsureLayoutTemplate();
            string qq = this.SortExpression;
            if (AutoQuery)
            {
                base.PerformSelect();
            }
            else
            {
                if (this.Page.IsPostBack)
                {
                    string eventId = Water.Web.Controls.Util.Utils.GeteEventId(this.Page);
                    foreach (string cId in this.QuerySource)
                    {
                        if (-1 != eventId.IndexOf(cId))
                        {
                            base.PerformSelect();
                            break;
                        }
                    }
                }
            }
        }

        private void RenderPackager(HtmlTextWriter writer)
        {
            if (!this.GridWidth.IsEmpty && this.gridWidth != Unit.Percentage(100))
                writer.AddStyleAttribute(HtmlTextWriterStyle.Width, this.GridWidth.ToString());
            if (DisplayGridBorder)
                writer.AddAttribute(HtmlTextWriterAttribute.Class, "default_g  default_g_b");
            else
                writer.AddAttribute(HtmlTextWriterAttribute.Class, "default_g");
        }

        protected override bool OnBubbleEvent(object source, EventArgs e)
        {
            if (((Control)source).UniqueID.IndexOf("$") != -1)
                this.isSelecting = true;
            return base.OnBubbleEvent(source, e);
        }

        protected override void OnItemUpdating(ListViewUpdateEventArgs e)
        {
            IOrderedDictionary _updateKeys = e.Keys;
            IOrderedDictionary _updateNewValues = e.NewValues;
            IOrderedDictionary _updateOldValues = e.OldValues;
            Hashtable _updateWhereFields = new Hashtable();
            Hashtable _updateFields = new Hashtable();

            //redo update process begin
            foreach (DictionaryEntry de in _updateKeys)
            {
                _updateWhereFields.Add(de.Key, de.Value);
            }
            e.Keys.Clear();
            e.Keys.Add("fields", _updateWhereFields);

            foreach (DictionaryEntry de1 in _updateNewValues)
            {
                if (null != _updateOldValues[de1.Key] && _updateOldValues.Contains(de1.Key) && _updateOldValues[de1.Key].ToString() != de1.Value.ToString())
                    _updateFields.Add(de1.Key, de1.Value);
                else if (null == _updateOldValues[de1.Key])
                    _updateFields.Add(de1.Key, de1.Value);
            }
            e.NewValues.Clear();
            e.NewValues.Add("updateFields", _updateFields);

            base.OnItemUpdating(e);
        }

        protected override void OnItemDeleting(ListViewDeleteEventArgs e)
        {
            IOrderedDictionary _deleteKeys = e.Keys;
            IOrderedDictionary _deleteValues = e.Values;
            Hashtable deleteFields = new Hashtable();
            //redo delete process begin
            foreach (DictionaryEntry de in _deleteKeys)
            {
                deleteFields.Add(de.Key, de.Value);
            }
            e.Keys.Clear();
            e.Keys.Add("fields", deleteFields);

            base.OnItemDeleting(e);
        }

        protected override void OnItemInserting(ListViewInsertEventArgs e)
        {
            IOrderedDictionary _indertValues = e.Values;
            Hashtable _insertFields = new Hashtable();

            foreach (DictionaryEntry de in _indertValues)
            {
                _insertFields.Add(de.Key, de.Value);
            }
            e.Values.Clear();
            e.Values.Add("fields", _insertFields);

            base.OnItemInserting(e);
        }

        #region IQuery 成员

        [Browsable(true), GlobalizeCategory("QUERY"), GlobalizeDescription("QueryTarget")]
        public string QueryTarget
        {
            get
            {
                return this.queryTarget;
            }
            set
            {
                this.queryTarget = value;
            }
        }

        [Browsable(false)]
        public List<string> QuerySource
        {
            get
            {
                return this.querySource;
            }
            set
            {
                this.querySource = value;
            }
        }

        #endregion
    }

    public class DefaultEmptyDataTemplate : DefaultLayoutTemplate
    {
        public DefaultEmptyDataTemplate(ListView listView)
            : base(listView)
        {
            this.IsEmptyDataTemplate = true;
        }

        protected override Control ItemPlaceholder()
        {
            Label label = new Label();
            label.Text = MessageResource.NoDataFound;
            return label;
        }
    }

    public class DefaultLayoutTemplate : ITemplate
    {
        private ListView parent;

        private bool isEmptyDataTemplate = false;

        protected bool IsEmptyDataTemplate
        {
            get { return isEmptyDataTemplate; }
            set { isEmptyDataTemplate = value; }
        }


        #region ITemplate 成员

        public DefaultLayoutTemplate(ListView listView)
        {
            this.parent = listView;
        }

        public void InstantiateIn(Control container)
        {
            HtmlGenericControl _rows_scroll = new HtmlGenericControl("div");
            _rows_scroll.Attributes["class"] = "default_g_rows_scroll";
            if (!parent.GridHeight.IsEmpty)
                _rows_scroll.Style.Add(HtmlTextWriterStyle.Height, parent.GridHeight.ToString());

            string id = parent.ClientID;
            Literal ajaxBegin = new Literal();
            Literal ajaxEnd = new Literal();

            HtmlGenericControl _rows_container = new HtmlGenericControl("div");
            _rows_container.Attributes["class"] = "default_g_rows_container";


            //itemplace holder
            _rows_container.Controls.Add(ItemPlaceholder());

            // ajax suppert

            if (parent is IUpdatedableControl)
            {
                _rows_container.Attributes["id"] = "__" + id + "__";
                ajaxBegin.PreRender += new EventHandler(ajaxBegin_PreRender);
                ajaxEnd.PreRender += new EventHandler(ajaxEnd_PreRender);
            }

            //if (!string.IsNullOrEmpty(ajaxBegin.Text))
            _rows_scroll.Controls.Add(ajaxBegin);

            _rows_scroll.Controls.Add(_rows_container);

            //if (!string.IsNullOrEmpty(ajaxEnd.Text))
            _rows_scroll.Controls.Add(ajaxEnd);

            //header
            container.Controls.Add(InstantiateInHeader());

            container.Controls.Add(_rows_scroll);

            //footer
            if (parent.ShowFooter)
                container.Controls.Add(InstantiateInFooter());

            //pager
            if (null != parent.PagerTemplate)
            {
                string id_p = parent.ClientID + "_p";
                Literal ajaxBegin_p = new Literal();
                Literal ajaxEnd_p = new Literal();
                HtmlGenericControl _pager = new HtmlGenericControl("div");
                _pager.Attributes["class"] = "default_g_pager";

                //ajax support
                if (parent is IUpdatedableControl)
                {
                    _pager.Attributes["id"] = "__" + id_p + "__";
                    ajaxBegin_p.PreRender += new EventHandler(ajaxBegin_PreRender_p);
                    ajaxEnd_p.PreRender += new EventHandler(ajaxEnd_PreRender_p);
                }

                container.Controls.Add(ajaxBegin_p);
                container.Controls.Add(_pager);
                container.Controls.Add(ajaxEnd_p);

                parent.PagerTemplate.InstantiateIn(_pager);
            }

        }

        void ajaxEnd_PreRender(object sender, EventArgs e)
        {
            ((Literal)sender).Text = Marker.GetAJAXEndMarker(parent);
        }
        void ajaxBegin_PreRender(object sender, EventArgs e)
        {
            ((Literal)sender).Text = Marker.GetAJAXBeginMarker(parent, parent.ClientID);
        }

        void ajaxEnd_PreRender_f(object sender, EventArgs e)
        {
            ((Literal)sender).Text = Marker.GetAJAXEndMarker(parent);
        }
        void ajaxBegin_PreRender_f(object sender, EventArgs e)
        {
            ((Literal)sender).Text = Marker.GetAJAXBeginMarker(parent, parent.ClientID + "_f");
        }

        void ajaxEnd_PreRender_p(object sender, EventArgs e)
        {
            ((Literal)sender).Text = Marker.GetAJAXEndMarker(parent);
        }
        void ajaxBegin_PreRender_p(object sender, EventArgs e)
        {
            ((Literal)sender).Text = Marker.GetAJAXBeginMarker(parent, parent.ClientID + "_p");
        }

        private Control InstantiateInHeader()
        {
            //DataView _mc= parent.MatrixColumns;

            HtmlGenericControl _header = new HtmlGenericControl("div");
            _header.Attributes["class"] = "default_g_header";

            HtmlGenericControl _header_container = new HtmlGenericControl("div");
            _header_container.Attributes["class"] = "default_g_header_container";

            Table table = new Table();
            table.CssClass = "default_g_header_table";
            TableRow row = new TableRow();

            int cellIndex = 0;

            List<DataControlField> _addColumns = new List<DataControlField>();
            List<DataControlField> _removeColumns = new List<DataControlField>();
            foreach (DataControlField dcf in parent.Columns)
            {
                if (dcf is Water.Web.Controls.BoundField)
                {
                    Water.Web.Controls.BoundField _bf = dcf as Water.Web.Controls.BoundField;
                    if (_bf.MatrixColumn)
                    {
                        foreach (DataRow _dr in parent.MatrixColumns.Table.Rows)
                        {
                            string _field = _dr[0].ToString();
                            BoundField _new_bf = new BoundField();
                            _new_bf.DataField = _field;
                            _new_bf.HeaderText = _field;
                            _new_bf.HeaderStyle.CopyFrom(_bf.HeaderStyle);
                            _new_bf.ItemStyle.CopyFrom(_bf.ItemStyle);
                            _new_bf.FooterStyle.CopyFrom(_bf.FooterStyle);
                            _new_bf.SummaryFunction = _bf.SummaryFunction;
                            _new_bf.NullDisplayText = _bf.NullDisplayText;
                            _new_bf.HeaderImageUrl = _bf.HeaderImageUrl;
                            _new_bf.AccessibleHeaderText = _bf.AccessibleHeaderText;
                            _new_bf.ApplyFormatInEditMode = _bf.ApplyFormatInEditMode;
                            _new_bf.ControlStyle.CopyFrom(_bf.ControlStyle);
                            _new_bf.ConvertEmptyStringToNull = _bf.ConvertEmptyStringToNull;
                            _new_bf.DataFormatString = _bf.DataFormatString;
                            _new_bf.HtmlEncode = _bf.HtmlEncode;
                            _new_bf.HtmlEncodeFormatString = _bf.HtmlEncodeFormatString;
                            _new_bf.ReadOnly = _bf.ReadOnly;
                            _new_bf.ShowHeader = _bf.ShowHeader;
                            _new_bf.Visible = _bf.Visible;

                            _addColumns.Add(_new_bf);
                        }
                        _removeColumns.Add(dcf);
                    }
                }
            }
            foreach (DataControlField _add_dcf in _addColumns)
            {
                parent.Columns.Add(_add_dcf);
            }

            foreach (DataControlField _remove_dcf in _removeColumns)
            {
                parent.Columns.Remove(_remove_dcf);
            }
            foreach (DataControlField dcf in parent.Columns)
            {
                CellProcess(dcf, ref  cellIndex, row);
            }

            table.Rows.Add(row);
            _header_container.Controls.Add(table);

            _header.Controls.Add(_header_container);

            return _header;
        }

        private Control InstantiateInFooter()
        {
            string id = parent.ClientID + "_f";
            Literal ajaxBegin = new Literal();
            Literal ajaxEnd = new Literal();

            HtmlGenericControl _footer = new HtmlGenericControl("div");
            _footer.Attributes["class"] = "default_g_footer";

            HtmlGenericControl _footer_container = new HtmlGenericControl("div");
            _footer_container.Attributes["class"] = "default_g_footer_container";

            //ajax support
            if (parent is IUpdatedableControl)
            {
                _footer_container.Attributes["id"] = "__" + id + "__";
                ajaxBegin.PreRender += new EventHandler(ajaxBegin_PreRender_f);
                ajaxEnd.PreRender += new EventHandler(ajaxEnd_PreRender_f);
            }

            Table table = new Table();
            table.CssClass = "default_g_footer_table";
            TableRow row = new TableRow();

            int cellIndex = 0;
            foreach (DataControlField dcf in parent.Columns)
            {
                DataControlFieldCell cell = new DataControlFieldCell(dcf);
                cell.CssClass = "default_gfc";
                cell.Attributes["axis"] = cellIndex++ + "";
                dcf.InitializeCell(cell, DataControlCellType.Footer, DataControlRowState.Normal, -1);

                //style
                if (!dcf.Visible)
                    cell.Visible = false;
                Style itemStyleInternal = dcf.FooterStyle;
                if (null != itemStyleInternal)
                    cell.MergeStyle(itemStyleInternal);
                //style end

                cell.DataBinding += new EventHandler(cell_DataBinding);
                cell.PreRender += new EventHandler(cell_PreRender);
                row.Cells.Add(cell);
            }
            table.Rows.Add(row);
            _footer_container.Controls.Add(table);

            //if (!string.IsNullOrEmpty(ajaxBegin.Text))
            _footer.Controls.Add(ajaxBegin);

            _footer.Controls.Add(_footer_container);

            //if (!string.IsNullOrEmpty(ajaxEnd.Text))
            _footer.Controls.Add(ajaxEnd);
            return _footer;
        }

        void cell_PreRender(object sender, EventArgs e)
        {
            DataControlFieldCell cell = (DataControlFieldCell)sender;
            if (cell.ContainingField is IDataControlFieldEx)
            {
                IDataControlFieldEx _dfce = cell.ContainingField as IDataControlFieldEx;
                if (SummaryType.No != _dfce.SummaryFunction)
                    cell.Text = _dfce.GetFormatAggregateDataValue(cell);
            }
        }

        protected virtual Control ItemPlaceholder()
        {
            PlaceHolder placeHolder = new PlaceHolder();
            placeHolder.ID = "itemPlaceholder";
            return placeHolder;
        }

        void cell_DataBinding(object sender, EventArgs e)
        {
            DataControlFieldCell cell = (DataControlFieldCell)sender;
            int cellIndex = int.Parse(cell.Attributes["axis"]);
            ListViewCellDataBoundEventArgs ee = new ListViewCellDataBoundEventArgs(cell, cellIndex, -1, DataControlCellType.Footer, DataControlRowState.Normal);
            parent.OnCellDataBound(ee);
        }

        private void CellProcess(DataControlField dcf, ref int cellIndex, TableRow row)
        {
            DataControlFieldCell cell = new DataControlFieldHeaderCell(dcf);
            cell.CssClass = "default_ghc";
            cell.Attributes["axis"] = cellIndex++ + "";
            if (!string.IsNullOrEmpty(dcf.SortExpression))
                dcf.Initialize(true, parent);
            dcf.InitializeCell(cell, DataControlCellType.Header, DataControlRowState.Normal, -1);

            //style
            if (!dcf.Visible)
                cell.Visible = false;
            Style headerStyleInternal = dcf.HeaderStyle;
            string width = dcf.HeaderStyle.Width.ToString();
            //headerStyleInternal.Width = Unit.Empty;
            if (null != headerStyleInternal)
                cell.MergeStyle(headerStyleInternal);


            if (!string.IsNullOrEmpty(width))
            {
                cell.Attributes["width"] = width;
            }
            else
                cell.Attributes["width"] = "150";

            //style end

            ListViewCellDataBoundEventArgs e = new ListViewCellDataBoundEventArgs(cell, cellIndex - 1, -1, DataControlCellType.Header, DataControlRowState.Normal);
            parent.OnCellDataBound(e);

            row.Cells.Add(cell);
        }
        #endregion
    }

    public class DefaultItemTemplate : ITemplate
    {
        private ListView parent;
        private int rowIndex;

        #region ITemplate 成员

        public DefaultItemTemplate(ListView listView)
        {
            this.parent = listView;
        }

        public void InstantiateIn(Control container)
        {
            if (null != container)
            {
                rowIndex = ((ListViewDataItem)container).DataItemIndex;

                HtmlGenericControl div = new HtmlGenericControl("div");
                div.Attributes["class"] = "default_g_rows";

                Table table = new Table();
                table.CssClass = "default_g_rows_table";

                TableRow row = new TableRow();

                int cellIndex = 0;

                DataControlRowState normal = DataControlRowState.Normal;
                if (rowIndex == this.parent.EditIndex)
                    normal = DataControlRowState.Edit;
                if (rowIndex == this.parent.SelectedIndex)
                    normal = DataControlRowState.Selected;

                foreach (DataControlField dcf in parent.Columns)
                {
                    DataControlFieldCell cell = new DataControlFieldCell(dcf);
                    cell.CssClass = "default_gc";
                    cell.Attributes["axis"] = cellIndex++ + "";
                    dcf.InitializeCell(cell, DataControlCellType.DataCell, normal, rowIndex);

                    //style
                    if (!dcf.Visible)
                        cell.Visible = false;
                    Style itemStyleInternal = dcf.ItemStyle;
                    if (null != itemStyleInternal)
                        cell.MergeStyle(itemStyleInternal);
                    //style end
                    cell.DataBinding += new EventHandler(cell_DataBinding);
                    row.Cells.Add(cell);


                }
                table.Rows.Add(row);
                div.Controls.Add(table);
                container.Controls.Add(div);
            }
        }

        void cell_DataBinding(object sender, EventArgs e)
        {
            DataControlFieldCell cell = (DataControlFieldCell)sender;
            int cellIndex = int.Parse(cell.Attributes["axis"]);
            ListViewCellDataBoundEventArgs ee = new ListViewCellDataBoundEventArgs(cell, cellIndex, rowIndex, DataControlCellType.DataCell, DataControlRowState.Normal);
            parent.OnCellDataBound(ee);
        }

        private void CellProcess(DataControlField dcf, ref int cellIndex, DataControlRowState normal, TableRow row)
        {
            DataControlFieldCell cell = new DataControlFieldCell(dcf);
            cell.CssClass = "default_gc";
            cell.Attributes["axis"] = cellIndex++ + "";
            dcf.InitializeCell(cell, DataControlCellType.DataCell, normal, rowIndex);

            //style
            if (!dcf.Visible)
                cell.Visible = false;
            Style itemStyleInternal = dcf.ItemStyle;
            if (null != itemStyleInternal)
                cell.MergeStyle(itemStyleInternal);
            //style end
            cell.DataBinding += new EventHandler(cell_DataBinding);
            row.Cells.Add(cell);
        }

        #endregion
    }

    public class DefaultAlternatingItemTemplate : ITemplate
    {
        private ListView parent;
        private int rowIndex;

        #region ITemplate 成员

        public DefaultAlternatingItemTemplate(ListView listView)
        {
            this.parent = listView;
        }
        public void InstantiateIn(Control container)
        {
            if (null != container)
            {
                rowIndex = ((ListViewDataItem)container).DataItemIndex;
                HtmlGenericControl div = new HtmlGenericControl("div");
                div.Attributes["class"] = "default_g_a_rows";

                Table table = new Table();
                table.CssClass = "default_g_a_rows_table";

                TableRow row = new TableRow();

                int cellIndex = 0;

                DataControlRowState alternate = DataControlRowState.Alternate;
                if (rowIndex == this.parent.EditIndex)
                    alternate = DataControlRowState.Edit;
                if (rowIndex == this.parent.SelectedIndex)
                    alternate = DataControlRowState.Selected;

                foreach (DataControlField dcf in parent.Columns)
                {
                    DataControlFieldCell cell = new DataControlFieldCell(dcf);
                    cell.CssClass = "default_gac";
                    cell.Attributes["axis"] = cellIndex++ + "";
                    dcf.InitializeCell(cell, DataControlCellType.DataCell, alternate, rowIndex);

                    //style
                    if (!dcf.Visible)
                        cell.Visible = false;
                    Style itemStyleInternal = dcf.ItemStyle;
                    if (null != itemStyleInternal)
                        cell.MergeStyle(itemStyleInternal);
                    //style end

                    cell.DataBinding += new EventHandler(cell_DataBinding);
                    row.Cells.Add(cell);
                }
                table.Rows.Add(row);
                div.Controls.Add(table);
                container.Controls.Add(div);
            }
        }

        void cell_DataBinding(object sender, EventArgs e)
        {
            DataControlFieldCell cell = (DataControlFieldCell)sender;
            int cellIndex = int.Parse(cell.Attributes["axis"]);
            ListViewCellDataBoundEventArgs ee = new ListViewCellDataBoundEventArgs(cell, cellIndex, rowIndex, DataControlCellType.DataCell, DataControlRowState.Alternate);
            parent.OnCellDataBound(ee);
        }

        #endregion
    }

    public delegate void ListViewCellDataBoundEventHandler(object sender, ListViewCellDataBoundEventArgs e);

    public class ListViewCellDataBoundEventArgs : EventArgs
    {
        private int cellIndex;
        private int rowIndex;
        private DataControlCellType cellType;
        private DataControlRowState rowState;
        private DataControlFieldCell cell;

        public ListViewCellDataBoundEventArgs(DataControlFieldCell cell, int cellIndex, int rowIndex, DataControlCellType cellType, DataControlRowState rowState)
        {
            this.cell = cell;
            this.cellIndex = cellIndex;
            this.rowIndex = rowIndex;
            this.cellType = cellType;
            this.rowState = rowState;
        }

        public int CellIndex
        {
            get { return cellIndex; }
        }
        public int RowIndex
        {
            get { return rowIndex; }
        }
        public DataControlCellType CellType
        {
            get { return cellType; }
        }
        public DataControlRowState RowState
        {
            get { return rowState; }
        }
        public DataControlFieldCell Cell
        {
            get { return cell; }
        }

    }
}
